﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lucene.Net.Analysis;
using System.IO;

namespace QueryResource.Common
{
    public class SqlCustomAnalyzer : Analyzer
    {
        public override TokenStream TokenStream(string fieldName, TextReader reader)
        {
            return new SqlCustomToken(reader);
        }
    }

    public class SqlCustomToken : Tokenizer
    {
        readonly TextReader _reader;
        public SqlCustomToken(TextReader reader)
        {
            _reader = reader;
        }
        //控制分词器只打开一次
        private bool _done = true;
        //当前读取到分词的记录数
        private int _ptr;
        //保存分词结果
        private List<Token> _tokenlist;

        [Obsolete("The new IncrementToken() and AttributeSource APIs should be used instead.")]
        public override Token Next(Token reusableToken)
        {
            if (_done)   //第一次可以运行，运行后将被设置为false,在一个实例中只会运行一次
            {
                _done = false;
                string text = _reader.ReadToEnd();
                //输入为空，则返回结束符号
                if (string.IsNullOrEmpty(text))
                    return null;
                //初始化分词结果
                _tokenlist = new List<Token>();
                //缓冲器，主要用于暂时保存英文数字字符。
                StringBuilder buffer = new StringBuilder(300);
                int first = 0;
                bool isJoin = false;
                bool isFrom = false;
                for (int i = 0; i < text.Length; i++)
                {
                    if (text[i] == ',')
                    {
                        AddToken(buffer.ToString().Trim(), first, i - 1, buffer);
                        first = i + 1;
                        continue;
                    }
                    buffer.Append(text[i]);
                    string content = buffer.ToString();
                    //空字符不考虑
                    if (content.Trim() == string.Empty)
                    {
                        buffer.Clear();
                        continue;
                    }
                    if (content.IndexOf("select", StringComparison.CurrentCultureIgnoreCase) >= 0)
                    {
                        isFrom = false;
                    }
                    string key = "from";
                    if (content.IndexOf(key, StringComparison.CurrentCultureIgnoreCase) >= 0)
                    {
                        AddToken(content.Trim(), first, i, buffer);
                        first = i + 1;
                        isFrom = true;
                        continue;
                    }
                    if (content.IndexOf("\r\n", StringComparison.Ordinal) >= 0 || 
                        content.IndexOf("\r", StringComparison.Ordinal) >= 0 ||
                        content.IndexOf("\n", StringComparison.Ordinal) >= 0)
                    {
                        AddToken(content.Trim(), first, i, buffer);
                        first = i + 1;
                        buffer.Clear();
                        continue;
                    }
                    key = "update ";
                    if (content.IndexOf(key, StringComparison.CurrentCultureIgnoreCase) >= 0)
                    {
                        AddToken(content.Remove(content.Length - key.Length).Trim(), first, i - key.Length, buffer);
                        AddToken(key, i - key.Length + 1, i, buffer);
                        isFrom = true;
                        buffer.Clear();
                        continue;
                    }
                    key = "join ";
                    if (content.IndexOf(key, StringComparison.CurrentCultureIgnoreCase) >= 0)
                    {
                        //AddToken(content.Remove(content.Length - key.Length).Trim(), first, i - key.Length, buffer);
                        //AddToken(key, i - key.Length + 1, i, buffer);
                        first = i + 1;
                        isJoin = true;
                        isFrom = false;
                        buffer.Clear();
                        continue;
                    }
                    key = "on";
                    if (isJoin && content.IndexOf(key, StringComparison.CurrentCultureIgnoreCase) > 0)
                    {
                        string[] leftjoins = content.Remove(content.Length - key.Length).Trim().Split(' ');
                        AddToken(leftjoins[0], 
                            first, 
                            first  + leftjoins[0].Length, 
                            buffer);
                        if (leftjoins.Length == 2)
                        {
                            AddToken(leftjoins[1],
                                first + leftjoins[0].Length + 1,
                                first + leftjoins[0].Length + 1 + leftjoins[1].Length,
                                buffer);
                        }
                        first = i + 1;
                        isJoin = false;
                        isFrom = true;
                        continue;
                    }
                    if (content.IndexOf("where ", StringComparison.CurrentCultureIgnoreCase) >= 0 ||
                        content.IndexOf("left ", StringComparison.CurrentCultureIgnoreCase) >= 0 ||
                        content.IndexOf("join ", StringComparison.CurrentCultureIgnoreCase) >= 0)
                    {
                        first = i + 1;
                        isFrom = false;
                        continue;
                    }

                    if (isFrom && (text[i] == ' ' || text[i] == ')'))
                    {
                        AddToken(content.Remove(content.Length - 1).Trim(), first, i - 1, buffer);
                        first = i + 1;
                    }
                  
                }
                if (buffer.Length > 0)
                {
                    Token token = new Token(buffer.ToString(), first, text.Length - 1);
                    _tokenlist.Add(token);
                    buffer.Clear();
                }
                //返回第一个分词结果，并且把指针移向下一位
                return _tokenlist[_ptr++];
            }
            //在分词结果范围内取词
            if (_ptr < _tokenlist.Count)
                return _tokenlist[_ptr++];
            //超出则返回结束符号
            return null;
        }

        private void AddToken(string content, int start, int end, StringBuilder buffer)
        {
            if (content == string.Empty)
                return;
            Token token = new Token(content, start, end);
            _tokenlist.Add(token);
            buffer.Clear();
        }
    }

    public static class AnalyzerEx
    {
        public static string AnalyzerFunc(this Analyzer analyzer, string testwords, string key,int index)
        {
            Dictionary<decimal,string> dic = new Dictionary<decimal,string>();
            List<string> list = new List<string>();
            TokenStream ts = analyzer.ReusableTokenStream("", new StringReader(testwords));
            Token token;
            object obj = null;

#pragma warning disable 612,618
            while((token = ts.Next()) != null)
#pragma warning restore 612,618
            {
                
                string text = token.TermText();
                if (text.ToUpper() == key.ToUpper() && obj != null)
                {
                    if (index > 0)
                    {
                        dic.Add( Math.Abs((decimal)(index - token.EndOffset())),obj.ToString());
                    }
                    else
                    {
                        list.Add(obj.ToString());
                    }
                }
                Console.WriteLine(token.TermText());
                if (text.ToUpper() != "AS")
                {
                    obj = text;
                }
            }
            ts.Close();
            if (dic.Count > 0)
            {
                return dic[dic.Keys.Min()];
            }
            if (list.Count == 0)
                return string.Empty;
            return list.LastOrDefault();
        }
    }
}
